package runnable_functions;

import gui.Main;

import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;

import javax.xml.parsers.ParserConfigurationException;

import org.xml.sax.SAXException;

import details.*;

/**
 * @author Tami
 *
 */
public class ADDfunctions extends RunnableClasses{
	
	
	
	
	public ADDfunctions(){}
	
	public  class AddNewCd implements Runnable{
		
		private Cd cd;
		private int length;
		private String discId;/* i assume that anna generates the genered-cd id , i only do the simple id*/
		private int[] trackLength;
		
		private CountDownLatch startSignal;
		
		public AddNewCd(String name,String performer,String genre,int year,ArrayList<Track> tracks,CountDownLatch startSignal){
			trackLength = new int[tracks.size()];
			System.out.println(tracks.size());
			for (int i = 0; i < tracks.size(); i++) {
				this.trackLength[i] = tracks.get(i).getLengthInSec();
			}
			this.length = computeCdLength(trackLength);
			this.discId = calculateDiscID(trackLength, tracks.size(), length);
			this.cd = new Cd(name,discId,0,performer,year,length,genre,0,0);
			this.cd.setTracks(tracks);
			this.startSignal = startSignal;
		}
		
		
		private  int computeCdLength(int trackLen[]){
			int len = 2;/* in sec*/
			for(int trackLength : trackLen){
				len += trackLength;
			}
			
			return len;
		}
		
		/**
		 *  
		 * calculate DISCID for adding new cd by user
		 * 
		 * Added by AnnaG
		 *
		 * @throws - throws SQLException  
		 * 
		 */


		private String calculateDiscID(int[] tracksLengthsInSecs, int numOfTracks, int CDtotalLength)
		{


			int checkSum = 0;


			int[] tracks_starting_times_in_secs = lengthsToSecOffsets(tracksLengthsInSecs, numOfTracks);

			for (int i = 0; i < numOfTracks; i++)
				checkSum += sumOfDigits(tracks_starting_times_in_secs[i]);

			int XX = checkSum % 255;
			int YYYY = CDtotalLength;
			int ZZ = numOfTracks;

			// XXYYYYZZ
			int dID =  ((XX << 24) | (YYYY << 8) | ZZ);
			String discID =  Integer.toHexString(dID);

			if (discID.length() == 7)
			{
				discID = "0" + discID;
			}

			return discID;


		}
		
		private  int sumOfDigits(int n) {
			int sum = 0;
			while (n > 0) {
				sum = sum + (n % 10);
				n = n / 10;
			}
			return sum;
		}
		
		private int[] lengthsToSecOffsets(int[] tracksLengthsInSecs, int numOfTracks)
		{
			int[] tracksTimeOffsets=new int[numOfTracks];

			tracksTimeOffsets[0] = 02;

			for (int i=1; i< numOfTracks; i++)
			{
				tracksTimeOffsets[i] = tracksTimeOffsets[i-1] + tracksLengthsInSecs[i-1];

			}

			return tracksTimeOffsets;
		}

/******************************************/
		
		
		

		public void run() {
			try{ 
				
				
				cd.addlyrics();
				Main.db.openConnection();
				
				
				
				Main.db.addCD(cd);
				Main.guiInt.notifySuccess();
			}catch(SQLException e){
				Main.guiInt.notifyDBFailure(e.toString());
			
			} catch (IllegalStateException e) {
				Main.guiInt.notifyDBFailure(e.toString());
			} catch (IOException e) {
				Main.guiInt.notifyDBFailure(e.toString());
			} catch (ParserConfigurationException e) {
				Main.guiInt.notifyDBFailure(e.toString());
			} catch (SAXException e) {
				Main.guiInt.notifyDBFailure(e.toString());
			} catch (InterruptedException e) {
				Main.guiInt.notifyDBFailure(e.toString());
			}
			
			finally{
				Main.db.closeConnection();
				startSignal.countDown();
			}
			}
			
		}

	

	
	
	public class AddSongComment implements Runnable{

		private String comment;
		private int songId;
		private User user;
		private String DATETIME;
		private ArrayList<Comment> comments;
		
		private CountDownLatch startSignal;
		
		public AddSongComment(String comment,int song_id,User user,String DATETIME,CountDownLatch startSignal){
			this.comment = comment;
			this.DATETIME = DATETIME;
			this.songId = song_id;
			this.user=user;
			this.startSignal = startSignal;
		}
		@Override
		public void run() {
		try{
			Main.db.openConnection();
			Main.db.addSongComment(songId, user.getIdNum(), DATETIME, comment);
			comments = Main.db.getSongComments(songId);
			Main.guiInt.refreshSongComments(comments);
			
		}catch(SQLException e){
			Main.guiInt.notifyDBFailure(e.toString());
			
		}
		finally{
			Main.db.closeConnection();
			startSignal.countDown();
		}
		}
		
	}
	
	public class AddSongLyric implements Runnable{

		private String lyric;
		private int songId;
		
		private CountDownLatch startSignal;

		
		public AddSongLyric(String lyric,int song_id,CountDownLatch startSignal){
			this.lyric = lyric;
			this.songId = song_id;
			this.startSignal = startSignal;
		}
		@Override
		public void run() {
		try{
			Main.db.openConnection();
			Main.db.addLyrics(songId, lyric);
			Main.guiInt.refreshSongLyric(lyric);
			
		}catch(SQLException e){
			
			Main.guiInt.notifyDBFailure(e.toString());
		}
		finally{
			Main.db.closeConnection();
			startSignal.countDown();
		}
		}
		
	}
	
	public class Like implements Runnable{

		private Target target;
		private String targetId;
		private User user ;
		private int likes;
		
		private CountDownLatch startSignal;
		
		public Like(User user,Target target,String targetId,CountDownLatch startSignal){
			this.target = target;
			this.targetId = targetId;
			this.user = user;
			this.startSignal = startSignal;
		}
		
		

		@Override
		public void run() {
			try{
				System.out.println("we are in add like trying to unlike(error)");
				Main.db.openConnection();
				Main.db.like_UnLike(targetId, target,details.Like.LIKE, user.getIdNum());
				likes = Main.db.getNumOfLikes(targetId, target);
				Main.guiInt.refreshUserLike(details.Like.LIKE);
				
				switch(target){
				case CD:
					Main.guiInt.refreshCdLikes(likes);
					break;
				case SONG:
					Main.guiInt.refreshSongLikes(likes);
					break;
				case ARTIST:
					Main.guiInt.refreshArtistLikes(likes);
					break;
				default:
					break;
				}
				
							
				
					
			}
			catch(SQLException e){
				Main.guiInt.notifyDBFailure(e.toString());
			}
			finally{
				Main.db.closeConnection();
				startSignal.countDown();
			}
		}
	}
}
	
	
